﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Linq;

namespace agilecards.Model
{
    public class CardDragManager
    {
        public CardDragManager(IMouseEventSource mouseEventSource, Canvas canvas)
        {
            mouseEventSource.MouseDown += new EventHandler<CanvasMouseEventArgs>(mouseEventSource_MouseDown);
            mouseEventSource.MouseUp += new EventHandler<CanvasMouseEventArgs>(mouseEventSource_MouseUp);
            mouseEventSource.MouseMove += new EventHandler<CanvasMouseEventArgs>(mouseEventSource_MouseMove);
            _canvas = canvas;
        }

        void mouseEventSource_MouseDown(object sender, CanvasMouseEventArgs e)
        {
            if (!FindAndRegisterCardAt(e.Position)) return;

            RegisterMouseLocation(e);
            RegisterIsMoving(true);
        }

        private bool FindAndRegisterCardAt(Point point)
        {
            _cardBeingMoved = GetCardAt(point);
            return _cardBeingMoved != null;
        }
        CardControl _cardBeingMoved = null;

        void mouseEventSource_MouseMove(object sender, CanvasMouseEventArgs e)
        {
            HandleMouseMoved(e);
        }

        void mouseEventSource_MouseUp(object sender, CanvasMouseEventArgs e)
        {
            RegisterIsMoving(false);
        }

        private void RegisterMouseLocation(CanvasMouseEventArgs e)
        {
            _lastPosition = GetPosition(e);
        }

        private void RegisterIsMoving(bool isMoving)
        {
            _isMoving = isMoving;
            if (isMoving == false)
            {
                _cardBeingMoved = null;
            }
        }

        private void HandleMouseMoved(CanvasMouseEventArgs e)
        {
            if (!_isMoving) return;
            MoveControl(e);
            RegisterMouseLocation(e);
        }

        private void MoveControl(CanvasMouseEventArgs e)
        {
            Point moveVector = CalculateMoveVector(e);
            Move(moveVector);
        }

        private void Move(Point moveVector)
        {
            Card card = (Card)_cardBeingMoved.DataContext;
            Point newCardPosition = new Point(
                card.Position.X + moveVector.X,
                card.Position.Y + moveVector.Y);
            card.Position = newCardPosition;
        }

        private Point CalculateMoveVector(CanvasMouseEventArgs e)
        {
            Point position = e.Position;
            return new Point(
                position.X - _lastPosition.X,
                position.Y - _lastPosition.Y);
        }

        private Point GetPosition(CanvasMouseEventArgs e)
        {
            return e.Position;
        }


        private bool HasHitACard(Point point)
        {
            var cards = GetCardsAt(point);
            return cards.Count() > 0;
        }

        private CardControl GetCardAt(Point point)
        {
            var cards = GetCardsAt(point);
            return cards.FirstOrDefault();
        }

        private IEnumerable<CardControl> GetCardsAt(Point point)
        {
            var cards = VisualTreeHelper.FindElementsInHostCoordinates(point, _canvas).OfType<CardControl>();
            return cards;
        }


        bool _isMoving = false;
        Point _lastPosition = new Point(0, 0);
        Canvas _canvas;
    }
}
